package com.nulldev.util.web.HttpServer3.extensions.nCaptcha.backend.util;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.nulldev.util.data.Variables;
import com.nulldev.util.web.HttpClient.util.HttpCookie;
import com.nulldev.util.web.HttpServer3.extensions.nCaptcha.backend.user.User;
import com.nulldev.util.web.HttpServer3.extensions.nCaptcha.backend.user.UserManager;
import com.nulldev.util.web.HttpServer3.pages.v3.HttpPage3.Request;

public class UUIDCookieLoader {

	public static boolean hasCookie(final Request req) {
		if (req == null)
			return false;
		if (!req.hasHeader("Cookie"))
			return false;

		final String cookieStr = req.header("Cookie");
		return cookieStr.contains("ncaptcha=");
	}

	public static boolean hasCookie(final Map<String, String> req) {
		if (req == null || req.isEmpty())
			return false;
		if (!req.containsKey("Cookie"))
			return false;

		final String cookieStr = req.get("Cookie");
		return cookieStr.contains("ncaptcha=");
	}

	public static User tryUserFromRequest(final Request req) {
		if (req == null) {
			return UserManager.makeUser();
		}

		if (!req.hasHeader("Cookie")) {
			return UserManager.makeUser();
		}

		final String cookieStr = req.header("Cookie");
		final List<HttpCookie> hc = HttpCookie.parse(cookieStr, /* breakSpecCompliance */ true);

		final Optional<HttpCookie> ncaptcha = hc.stream().filter((cookie) -> cookie.getName().equals("ncaptcha") && !cookie.hasExpired()).findAny();
		if (ncaptcha.isPresent()) {
			final String uuid = ncaptcha.get().getValue();

			return UserManager.loadUserOrMake(uuid);
		} else {
			return UserManager.makeUser();
		}
	}

	public static User userFromRequest(final Request req) {
		if (req == null)
			return null;

		if (!req.hasHeader("Cookie"))
			return null;

		final String cookieStr = req.header("Cookie");
		final List<HttpCookie> hc = HttpCookie.parse(cookieStr, /* breakSpecCompliance */ true);

		final Optional<HttpCookie> ncaptcha = hc.stream().filter((cookie) -> cookie.getName().equals("ncaptcha") && !cookie.hasExpired()).findAny();
		if (ncaptcha.isPresent()) {
			return UserManager.loadUser(ncaptcha.get().getValue());
		} else {
			return null;
		}
	}

	public static String makeCookieFromUUID(final User u) {
		Variables.requireNonNull(u, "u");
		final String uuid = u.uuid();
		final long expiry = u.time() / 1000;

		/* "Partitioned" seems to make Firefox and Chrome unhappy */
		return String.format("ncaptcha=%s; Max-Age=%d; Path=/; SameSite=Strict;", uuid, expiry);
	}

	public static boolean validateFromHeaders(final Map<String, String> headers) {
		if (headers == null || headers.isEmpty())
			return false;
		if (!headers.containsKey("Cookie"))
			return false;

		final String cookieStr = headers.get("Cookie");
		final List<HttpCookie> hc = HttpCookie.parse(cookieStr, /* breakSpecCompliance */ true);

		final Optional<HttpCookie> ncaptcha = hc.stream().filter((cookie) -> cookie.getName().equals("ncaptcha") && !cookie.hasExpired()).findAny();
		if (ncaptcha.isPresent()) {
			return UserManager.isCaptchaComplete(ncaptcha.get().getValue());
		} else {
			return false;
		}
	}
}
